# Примеры использования grep
Примеры команды запуска grep:

    grep -i 'hello.*world' menu.h main.c
Это выводит список всех строк в файлах menu.h и main.c, которые содержат строку «hello», за которой следует строка «world»; .* означает ноль или более любых символов, т.е. между «hello» и «world» могут содержаться любые символы и эта строка будет считаться соответствующей шаблону. Опция -i говорит grep игнорировать регистр букв, что приводит к тому, что строка «Hello, world!», которая в противном случае не соответствовала, также будет считаться подходящей.

Далее несколько популярных вопросов и ответов об использовании grep с примерами вызова этой программы.

## Как можно вывести список только имён файлов, в которых найдено совпадение?

    grep -l 'main' *.c
выведет имена всех C файлов в текущей директории, чей контент упоминает «main».

## Как рекурсивно искать по директориям?

    grep -r 'hello' /home/gigi
поиск ‘hello’ во всех файлах в директории /home/gigi. Для дополнительного контроля за файлами для поиска, используйте find, grep и xargs. Например, следующая команда делает поиск только по файлам C:

ind /home/gigi -name '*.c' -print0 | xargs -0r grep -H 'hello'
Она отличается от этой команды:

    grep -H 'hello' *.c
которая только ищет «hello» во всех файлах в текущей директории, чьё имя заканчивается на «.c». Команда выше «find …» более похожа на команду:

    grep -rH --include='*.c' 'hello' /home/gigi
## Что если шаблон начинается с «-»?

    grep -e '--cut here--' *
ищет все строки, совпадающие с «--cut here--». Без -e, grep будет пытаться разобрать «--cut here--» как список опций.

## Допустим я хочу искать по целому слову, а не по части слова?

    grep -w 'hello' *
ищет только экземпляры «hello» которые являются целым словом; она не найдёт «Othello». Для большего контроля используйте «\<» и «\>» для совпадения начала и конца слов. Например:

    grep 'hello\>' *
ищет только слова, оканчивающиеся на «hello», поэтому оно будет соответствовать слову «Othello».

## Как я могу вывести контекст вокруг совпадающих строк?

    grep -C 2 'hello' *
печатает две строки контекста вокруг подошедшей строки.

## Как принудить grep печатать имя файла?

Добавьте /dev/null:

    grep 'mial' /etc/passwd /dev/null
даст вам:

    /etc/passwd:mial:x:1000:100::/home/mial:/bin/bash
Альтернативно используйте -H, которая является расширением GNU:

    grep -H 'mial' /etc/passwd
## Почему используют странное регулярное выражение для вывода ps?

    ps -ef | grep '[c]ron'
Если бы шаблон был написан без квадратных кавычек, то он бы соответствовал не только ps выводу для cron, но также строке ps вывода для grep. Обратите внимание, что на некоторых платформах ps ограничивает вывод на ширину экрана; grep не имеет каких-либо лимитов на длину строки, кроме доступной памяти.

## Почему grep пишет «Двоичный файл совпадает» («Binary file matches»)?

Если grep выводит все совпавшие «строки» из бинарного файла, она, вероятно, сгенерирует вывод, который бесполезен и даже может испортить вид. Поэтому GNU grep подавляет вывод из файлов, которые кажутся бинарными файлами. Чтобы заставить GNU grep выводить строки даже из файлов, которые похожи на бинарные, используйте опцию -a или «--binary-files=text». Для устранения сообщения «Двоичный файл совпадает», используйте опцию -I или «--binary-files=without-match».

## Почему «grep -lv» не печатает файлы без совпадений?

«grep -lv» выводит имена всех файлов, содержащих одну или более строк, которые не совпадают. Для вывода имён всех файлов, которые не содержат совпадающие строки, используйте опцию -L или --files-without-match.

## Я могу делать «ИЛИ» с «|», а что насчёт «И»?

    grep 'paul' /etc/motd | grep 'franc,ois'
найдёт все строки, которые содержат и «paul» и «franc,ois».

## Почему пустой шаблон соответствует каждой строке ввода?

Команда grep ищет строчки, которые содержат строки, соответствующие шаблону. Каждая строчка содержит пустую строку, поэтому пустой шаблон приводит к тому, что grep находит соответствие на каждой строке. Не только пустой шаблон, также «^» (каждая строка имеет начало), «$» (каждая строка имеет окончание), «.*» (соответствует чему угодно) и многие другие шаблоны делают так, что grep находит совпадение в каждой строке.

Для совпадения с пустыми строками используйте шаблон «^$». Для совпадения с чистыми строками, используйте шаблон «^[[:blank:]]*$». Чтобы не было найдено ни одного совпадения, используйте команду «grep -f /dev/null».

## Как я могу искать одновременно в стандартном вводе и в файлах?

Используйте специальное имя файла «-»:

    cat /etc/passwd | grep 'alain' - /etc/motd
## Как выразить палиндромы в регулярных выражениях?

Это можно сделать используя обратные сслыки; например, палиндром из четырёх символов:

    grep -w -E '(.)(.).\2\1' файл
Это будет соответствовать слову «radar» или «civic».

Поиск палиндромов из пяти букв в стандартном словаре:

    grep -w -E '(.)(.).\2\1' /usr/share/dict/american-english
Guglielmo Bondioni предложил единое регулярное выражение, которое находит все палиндромы до 19 символов длинной, используя 9 подвыражений и 9 обратных ссылок:

    grep -E '^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\9\8\7\6\5\4\3\2\1$' файл
## Почему эта обратная ссылка не работает?

    echo 'ba' | grep -E '(a)\1|b\1'
Здесь ничего не будет выведено, поскольку первая альтернатива «(a)\1» не имеет совпадений, ведь во вводе отсутствует «aa», из-за этого «\1» во второй альтернативе не на что ссылаться, что означает, что она также не будет совпадать. В этом примере вторая альтернатива может совпасть только если  совпала первая альтернатива – делая вторую излишней.

## Как можно искать совпадения сразу по нескольким строкам?

Стандартная grep не может делать это, поскольку в своей основе её работа основана на построчной обработке. Следовательно, просто использование класса символов [:space:] не обработает новую строку (newline) тем способом, как вы могли бы ожидать.

С опцией -z (--null-data) GNU grep, каждый ввод и вывод «строчки» разделён символом null; смотрите Остальные опции. Следовательно, вы можете составлять регулярные выражения с использования символа новая строка (newline), но обычно если имеется совпадение, то будет выведен весь ввода, следовательно, это использование часто комбинируется с опциями, подавляющими вывод, такой как -q, например:

    printf 'foo\nbar\n' | grep -z -q 'foo[[:space:]]\+bar'
Если это недостаточно, вы можете трансформировать ввод перед передачей его в grep, или задействуйте awk, sed, perl или любые другие утилиты, которые предназначены для работы через строки.

## Как использовать grep для поиска по стандартному выводу ошибок (stderr)

grep может работать только со стандартным вводом. Это канал, созданный оболочкой, который соединяет stdin grep с stdout другой команды. И оболочка может подключать только стандартный вывод к стандартному вводу.

Но варианты обойти эту проблему всё равно имеются.

Во-первых, можно просто перенаправить поток ошибок в стандартный вывод и использовать grep как обычно:

    fmpeg -i 01-Daemon.mp3 2>&1 | grep -i Duration
    Duration: 01:15:12.33, start: 0.000000, bitrate: 64 kb/s
Но что если мы не хотим перенаправлять stderr в stdout?

У этой проблемы также есть решение!

В bash вы можете воспользоваться анонимными каналами:

    ffmpeg -i 01-Daemon.mp3 2> >(grep -i Duration)
Обратите внимание, что целевая команда подстановки процесса выполняется асинхронно. Как следствие, строки stderr, которые проходят через фильтр grep, могут не отображаться в том месте, которое вы ожидаете в остальной части вывода, и даже не в следующем приглашении командной строки.

В следующей команде показан пример, когда grep ищет совпадения в потоке вывода ошибок, а стандартный вывод уничтожается:

    curl -v 100.19.18.59 2> >(grep -o -i -E Unauthorized) > /dev/null


Дело в том, что HTTP заголовки команда cURL выводит в stderr, а команда grep не ищет по stderr. Но мы не может сделать просто перенаправление stderr для слияния со стандартным выводом, то есть не можем 2>&1, поскольку текст страницы может содержать слово «Unauthorized» и мы получим ложное срабатывание. Поэтому мы используем указанную выше конструкцию — вывод ошибок обрабатывается, стандартный вывод уничтожается.

